﻿
#region Using Directives.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Text;

#endregion

namespace RWXMLEdit.Common
{
    public class Functions
    {
        #region Public Methods.

        public static void CheckValues(ref double[] values, double minValue, double maxValue)
        {
            for(int i = 0; i < values.Length; i++)
            {
                if (values[i] > maxValue)
                    values[i] = maxValue;

                if (values[i] < minValue)
                    values[i] = minValue;
            }
        }

        public static double CheckValue(double value, double minValue, double maxValue)
        {
            double tmp = value;

            if (tmp > maxValue)
                tmp = maxValue;

            if (tmp < minValue)
                tmp = minValue;

            return tmp;
        }

        public static string BuildResultString(double[] values)
        {
            StringBuilder sb = new StringBuilder();

            //sb.AppendLine(string.Format("        0\t\t    1\t\t    2\t\t    3"));
            //sb.AppendLine(string.Format("  -------------------------------------------------------------------------------"));
            sb.AppendLine(String.Format("{0}             {1}             {2}             {3}", FormatValue(values[0]), FormatValue(values[1]), FormatValue(values[2]), FormatValue(values[3])));
            sb.AppendLine(String.Format("{0}             {1}             {2}             {3}", FormatValue(values[4]), FormatValue(values[5]), FormatValue(values[6]), FormatValue(values[7])));
            sb.AppendLine(String.Format("{0}             {1}             {2}             {3}", FormatValue(values[8]), FormatValue(values[9]), FormatValue(values[10]), FormatValue(values[11])));
            sb.AppendLine(String.Format("{0}             {1}             {2}             {3}", FormatValue(values[12]), FormatValue(values[13]), FormatValue(values[14]), FormatValue(values[15])));

            return sb.ToString();
        }

        public static FileInfoTypes CheckFileStatus(string path, string md5CheckSum)
        {
            if(!File.Exists(path) && !String.IsNullOrEmpty(md5CheckSum))
            {
                return FileInfoTypes.FileIsMissing;
            }

            if(IsFileReadOnly(path))
            {
                return FileInfoTypes.FileIsWriteProtected;
            }

            string currentMd5CheckSum = RwHasher.GetMd5Hash(path);

            if(md5CheckSum == currentMd5CheckSum ||  String.IsNullOrEmpty(md5CheckSum))
            {
                return FileInfoTypes.FileIsOk;
            }
            return FileInfoTypes.FileIsChanged;
        }

        public static string FormatValue(double value)
        {
            string temp = String.Empty;

            if(value >= 0)
            {
                temp = String.Format(" {0:0.#####0}", value);
            }
            else
            {
                temp = String.Format("{0:0.#####0}", value);
            }

            temp = temp.Replace(",", ".");

            return temp;
        }

        public static string[] FormatValues(double[] arr)
        {
            var retArr = new string[arr.Length];

            for (int i = 0; i < arr.Length; i++)
            {
                string temp = String.Format("{0:0.#####0}", arr[i]);

                temp = temp.Replace(",", ".");

                retArr[i] = temp;
            }

            return retArr;
        }

        public static void AddSFloat32Tags(ref XElement element)
        {
            string[] defaultValues = GetDefaultStringValues();

            XElement tempElement = (from x in element.DescendantsAndSelf()
                                    where (string)x.Attribute("name") == "Element"
                                    select x).SingleOrDefault();

            for (int i = 1; i <= 16; i++)
            {
                var xe = new XElement("sFloat32", new XElement("Element", new XElement("Value", defaultValues[i - 1])));

                if (tempElement != null)
                {
                    var xElement = tempElement.Element("__Indexed__sFloat32");
                    if (xElement != null)
                    {
                        var xElement1 = xElement.Element("Element");
                        if (xElement1 != null)
                        {
                            var element1 = xElement1.Element("Value");
                            if (element1 != null) element1.Add(xe);
                        }
                    }
                }
            }
        }

        public static double[] GetDefaultDoubleValues()
        {
            double[] defaultValues = {
                                          1.000000, 0.000000, 0.000000, 0.000000,
                                          0.000000, 1.000000, 0.000000, 0.000000,
                                          0.000000, 0.000000, 1.000000, 0.000000,
                                          0.000000, 0.000000, 0.000000, 1.000000
                                      };

            return defaultValues;
        }

        public static string[] GetDefaultStringValues()
        {
            string[] defaultValues = {
                                          "1.000000", "0.000000", "0.000000", "0.000000",
                                          "0.000000", "1.000000", "0.000000", "0.000000",
                                          "0.000000", "0.000000", "1.000000", "0.000000",
                                          "0.000000", "0.000000", "0.000000", "1.000000"
                                      };

            return defaultValues;
        }

        public static bool DeleteTempFiles(List<string> files)
        {
            try
            {
                foreach (string file in files)
                {
                    File.Delete(file);
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public static string GetTemporaryFileName(string extn)
        {
            if (!extn.StartsWith("."))
            {
                extn = String.Format(".{0}", extn);
            }

            return String.Format("{0}{1}{2}", Path.GetTempPath(), Guid.NewGuid(), extn);
        }

        public static List<string> GetAllViewNames(XmlDocument document)
        {
            var retval = new List<string>();
            XmlNodeList nodeList = document.GetElementsByTagName("viewClass");

            foreach (XmlNode node in nodeList)
            {
                if (node.Attributes != null)
                {
                    retval.Add(node.Attributes["Name"].Value);
                }
            }

            return retval;
        }

        public static List<string> CreateStringArrayLines(string text)
        {
            var lines = new List<string>();

            string[] temp = text.Split('\n');

            lines.AddRange(temp);

            return lines;
        }

        public static bool ValidateKeyChar(char key)
        {
            // Try converting the introduced char value to a byte value
            byte i;
            bool parsed = Byte.TryParse(key.ToString(), out i);
            bool val;

            //If convresion succeeded, show allow character.
            if (parsed)
            {
                val = false;
            }
            // If the conversion did not succeed, check if the pressed
            // button was Backspace (char code is 8) or Delete (char code is 46).
            else
            {
                switch (Convert.ToInt32(key))
                {
                    case 8:
                        val = false;  // If Backspace, allow char.
                        break;
                    case 46:
                        val = false;  // If Delete, allow char.
                        break;
                    default:
                        val = true;
                        break;
                }
            }
            return val;
        }

        public static bool IsFileReadOnly(string path)
        {
            if (String.IsNullOrEmpty(path))
                return false;

            FileInfo file = new FileInfo(path);
                      
            if ((file.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
            {
                return true;
            }

            return false;
        }

        public static string InvertCasing(string text)
        {
            if (text == null)
                return String.Empty;

            StringBuilder sb = new StringBuilder();
            foreach (char c in text)
            {
                if (Char.IsLower(c))
                    sb.Append(Char.ToUpper(c));
                else if (Char.IsUpper(c))
                    sb.Append(Char.ToLower(c));
                else
                {
                    sb.Append(c);
                }
            }

            return sb.ToString();
        }

        public static string IndentedXml(string xml, int indent)
        {
            var doc = new XmlDocument();
            doc.LoadXml(xml);

            using (var ms = new MemoryStream())
            using (var writer = new XmlTextWriter(ms, Encoding.UTF8))
            using (var sr = new StreamReader(ms))
            {
                writer.Formatting = Formatting.Indented;
                writer.Indentation = 4;
                doc.Save(writer);
                ms.Position = 0;

                return sr.ReadToEnd();
            }
        }

        /// <summary>
        /// Formats the provided XML so it's indented and humanly-readable.
        /// </summary>
        /// <param name="inputXml">The input XML to format.</param>
        /// <returns></returns>
        public static string FormatXml(string inputXml)
        {
            XmlDocument document = new XmlDocument();

            if (inputXml.Contains("xmlns=\"http://schemas.microsoft.com/dsltools/WmBofDSL\""))
            {
                inputXml = inputXml.Replace("xmlns=\"http://schemas.microsoft.com/dsltools/WmBofDSL\"", "");
            }

            document.Load(new StringReader(inputXml));

            StringBuilder builder = new StringBuilder();

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.OmitXmlDeclaration = true;
            //settings.ConformanceLevel = ConformanceLevel.Fragment;
            settings.Indent = true;

            XmlWriter writer = XmlWriter.Create(new StringWriterEx(Encoding.UTF8, builder), settings);

            document.Save(writer);

            writer.Close();

            return builder.ToString();
        }

        #endregion

        #region Private Methods.

        public static string GetPersonalFolder()
        {
            return Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        }

        #endregion
    }
}